<template>
    <div style="width: 49%;" :style="{fontSize: `${fontsize}px`}">
        <canvas style="width: 100%; height: auto; aspect-ratio:1/1;" id="moonPhaseCanvas"></canvas>
        <div class="phase">{{currentPhaseName}}</div>
    </div>
</template>

<script setup lang="ts">
import { onMounted, onUnmounted, ref, watch } from 'vue';
import { getMoonPhase, type RawMoonPhase } from '../api';
import type { Setting } from '../App.vue';

const props = defineProps<{
    setting: Setting
}>();

let canvas: HTMLCanvasElement | null = null;

const darkColor = "#222";
const lightColor = "#FFFFFF";


const draw = (phase: RawMoonPhase)=>{
    if (!canvas) return

    // 基本圆
    const ctx = canvas.getContext('2d');
    if (!ctx) return;
    const width = canvas.clientWidth;
    const height = canvas.clientHeight;
    canvas.width = width;
    canvas.height = height;
    const x0 = width / 2;
    const y0 = height / 2;

    const R = Math.min(width, height) / 2;
    ctx.clearRect(0, 0, width, height);
    ctx.fillStyle = '#000';
    ctx.fillRect(0, 0, width, height);


    // 叠加月球图片
    const moonImg = new Image();
    moonImg.src = new URL("../assets/moon.jpg", import.meta.url).href;
    moonImg.onload = () => {
        const m = R ; // 月球大小
        ctx.save();
        ctx.translate(x0, y0);
        ctx.rotate(50/180 * Math.PI); // 旋转30度
        ctx.globalAlpha = 0.6; // 设置半透明，值范围0-1，可以根据需要调整
        ctx.drawImage(moonImg, -m, -m, m * 2, m * 2);
        ctx.globalAlpha = 1; // 恢复透明度为默认值
        ctx.restore();
    };

    ctx.fillStyle = lightColor;
    ctx.beginPath();
    ctx.arc(x0, y0, R, 0, Math.PI * 2);
    ctx.fill();

    // angle =0 时为满月, 为 -pi 时为新月，小于零为上弦月，大于零为下弦月
    ctx.fillStyle = darkColor;

    let phaseAngel = phase.phase * Math.PI * 2;
    let rotate = (Math.PI / 2) + phase.angle;
    if (phase.phase < 1/2) {
        // 上弦月左边暗右边亮
        // 先覆盖左边半圆
        ctx.beginPath();
        ctx.arc(x0, y0, R, Math.PI / 2 -rotate, Math.PI * 3 / 2-rotate);
        ctx.fill();

        if (phase.phase < 1/4){
            ctx.fillStyle = darkColor;
            ctx.beginPath();
            const r = Math.sin((Math.PI / 2) - phaseAngel) * R;
            ctx.ellipse(x0, y0, r, R, -rotate, 0, Math.PI*2);
            ctx.fill();
        } else {
            // 画上弦月的亮部分
            ctx.fillStyle = lightColor;
            ctx.beginPath();
            const r = Math.sin(phaseAngel - (Math.PI / 2)) * R;
            ctx.ellipse(x0, y0, r, R, -rotate, 0, Math.PI * 2)
            ctx.fill();
        }
    }
    else if (phase.phase == 1/2){
        // 满月
        ctx.fillStyle = lightColor;
        ctx.beginPath();
        ctx.arc(x0, y0, R, 0, Math.PI * 2);
        ctx.fill();
    }
    else {
        // 下弦月右边暗左边亮
        // 先覆盖右边半圆
        rotate -= (Math.PI);
        ctx.beginPath();
        ctx.arc(x0, y0, R, -Math.PI / 2 -rotate, Math.PI / 2 -rotate);
        ctx.fill();

        phaseAngel -= Math.PI;

        if (phase.phase < 3/4){
            ctx.fillStyle = lightColor;
            ctx.beginPath();
            const r = Math.sin((Math.PI / 2) - phaseAngel) * R;
            ctx.ellipse(x0, y0, r, R, -rotate, 0, Math.PI * 2);
            ctx.fill();
        } else {
            // 画下弦月的亮部分
            ctx.fillStyle = darkColor;
            ctx.beginPath();
            const r = Math.sin(phaseAngel - (Math.PI / 2)) * R;
            ctx.ellipse(x0, y0, r, R, -rotate, 0, Math.PI * 2);
            ctx.fill();
        }
    }

}

const moonPhaseList = [
    {s: 0, e: 0.05, name: '朔月'},
    {s: 0.05, e: 0.2, name: '蛾眉月'},
    {s: 0.2, e: 0.3, name: '上弦月'},
    {s: 0.3, e: 0.45, name: '盈凸月'},
    {s: 0.45, e: 0.55, name: '望月'},
    {s: 0.55, e: 0.7, name: '亏凸月'},
    {s: 0.7, e: 0.8, name: '下弦月'},
    {s: 0.8, e: 0.95, name: '残月'},
    {s: 0.95, e: 1, name: '朔月'},
]

const currentPhaseName = ref('');

const setPhaseName = (phase: RawMoonPhase) => {
    let text = '新月';
    for (const item of moonPhaseList) {
        if (phase.phase >= item.s && phase.phase < item.e) {
            text = item.name;
            break;
        }
    }

    text += ` (照亮 ${Math.round(phase.fraction * 100)}%)`;
    currentPhaseName.value = text;
}

const update = ()=>{
    let time = new Date();
    const phase = getMoonPhase(time);
    draw(phase);
    setPhaseName(phase);
}

let timer: number | null = null;
let obs: ResizeObserver | null = null;
const fontsize = ref(10);

const setSize = ()=>{
    const width = document.getElementById('moonPhaseCanvas')?.clientWidth;
    if(width) {
        fontsize.value = width / 25;
    }
}

onMounted(()=>{
    canvas = document.getElementById('moonPhaseCanvas') as HTMLCanvasElement;
    timer = setInterval(()=>{ update(); }, props.setting.moonInterval * 1000);
    update();
    setSize();
    obs = new ResizeObserver(setSize);
    obs.observe(document.getElementById('rightBox') as HTMLElement);
})

watch(() => props.setting, () => {
    if (timer) {
        clearInterval(timer);
    }
    timer = setInterval(()=>{ update(); }, props.setting.moonInterval * 1000);
    update();
});

onUnmounted(()=>{
    if (timer) {
        clearInterval(timer);
    }
    if (obs) {
        obs.disconnect();
    }
});

</script>

<style scoped>
.phase{
    width: 100%;
    text-align: center;
    font-size: 1em;
    color: #a4a4a4;
}
</style>